﻿using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;

namespace TicketMLib
{
    public class Utils
    {
        private static string ProcessConfigPath;
        private string RoutingConfigPath;
        private string TicketDefPath;
        private string ProjectsPath;

        public Utils()
        {
            ProcessConfigPath = "/Configuration/TicketProcessingService.exe.config";
            RoutingConfigPath = "/App_Data/AreasStruct.xml";
            TicketDefPath = "/App_Data/Ticket.xml";
            ProjectsPath = "/App_Data/Projects.xml";
        }
        #region General Methods
        public static TfsTeamProjectCollection Connect2Tfs(string uName, string passwd, string domain, string tfs, string collection)
        {
            NetworkCredential crednetial = new NetworkCredential(uName, passwd, domain);
            TfsTeamProjectCollection tpc;
            string _uri = "http://" + tfs + ":8080/tfs/" + collection;
            try
            {
                tpc = new TfsTeamProjectCollection(new Uri(_uri), crednetial);
            }
            catch
            {

                throw;
            }
            return tpc;
        }
        public static void SetGenVarValues(string sProject, out string uName, out string passwd, out string domain, out string tfs, out string collection, out string _project)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(HttpContext.Current.Server.MapPath(ProcessConfigPath));
                uName = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='UserName']").Attributes["value"].Value;
                passwd = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Password']").Attributes["value"].Value;
                domain = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Domain']").Attributes["value"].Value;
                tfs = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Tfs']").Attributes["value"].Value;
                collection = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='Collection']").Attributes["value"].Value;
                _project = sProject;
            }
            catch
            {

                throw;
            }
        }
        public ArrayList GetTeamMembers(string sProject)
        {
            ArrayList UsersAL = new ArrayList();
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                var gss = tpc.GetService<IGroupSecurityService>();
                Identity SIDs = gss.ReadIdentity(SearchFactor.AccountName, "[" + project.Name + "]\\Contributors", QueryMembership.Expanded);
                Identity[] Users = gss.ReadIdentities(SearchFactor.Sid, SIDs.Members, QueryMembership.Direct);
                foreach (Identity user in Users)
                {

                    if (user.SecurityGroup)
                    {
                        UsersAL.Add("[project]\\" + user.DisplayName);
                    }
                    else
                    {
                        UsersAL.Add(user.DisplayName);
                    }

                }
            }
            catch
            {
                throw;
            }
            return UsersAL;
        }
        public ArrayList GetTeamMembersEmails(string sProject)
        {
            ArrayList UsersEmailsAL = new ArrayList();
            try
            {
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion

                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                var gss = tpc.GetService<IGroupSecurityService>();
                Identity SIDs = gss.ReadIdentity(SearchFactor.AccountName, "[" + project.Name + "]\\Contributors", QueryMembership.Expanded);
                Identity[] Users = gss.ReadIdentities(SearchFactor.Sid, SIDs.Members, QueryMembership.Direct);
                foreach (Identity user in Users)
                {

                    if (!user.SecurityGroup)
                    {
                        UsersEmailsAL.Add(user.MailAddress);
                    }
                }
            }
            catch
            {

                throw;
            }
            return UsersEmailsAL;
        }
        public ArrayList GetProjects()
        {
            ArrayList projects = new ArrayList();
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            try
            {
                SetGenVarValues("", out uName, out passwd, out domain, out tfs, out collection, out _project);
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                WorkItemStore store = (WorkItemStore)tpc.GetService(typeof(WorkItemStore));
                foreach (Project project in store.Projects)
                {
                    projects.Add(project.Name);
                }
            }
            catch
            {

                throw;
            }
            return projects;

        }

        public bool AddTicketWIT2Project(string sProject, string ProjectsFilePath, string EscalationsFilePath)
        {
            bool retval = false;
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion
            try
            {
                TfsTeamProjectCollection tpc = Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                XmlDocument doc1 = new XmlDocument();
                //doc1.Load(HttpContext.Current.Server.MapPath("/App_Data/Ticket.xml"));
                doc1.Load(HttpContext.Current.Server.MapPath(TicketDefPath));
                project.WorkItemTypes.Import(doc1.DocumentElement);
                XmlDocument doc2 = new XmlDocument();
                doc2.Load(HttpContext.Current.Server.MapPath(ProjectsFilePath));
                XmlNode root = doc2.DocumentElement;
                XmlNode node = root.SelectSingleNode("//projects");
                XmlNode NewProductNode = doc2.CreateNode(XmlNodeType.Element, "project", null);
                XmlAttribute nameAttrib = doc2.CreateAttribute("name");
                nameAttrib.Value = _project;
                NewProductNode.Attributes.Append(nameAttrib);

                //append it at appropriate place
                node.AppendChild(NewProductNode);
                doc2.Save(HttpContext.Current.Server.MapPath(ProjectsFilePath));

                XmlDocument doc3 = new XmlDocument();
                doc3.Load(HttpContext.Current.Server.MapPath(EscalationsFilePath));
                XmlNode root3 = doc3.DocumentElement;
                XmlNode node3 = root3.SelectSingleNode("//Area_Email_Days");
                XmlNode NewAreaNode = doc3.CreateNode(XmlNodeType.Element, "Area", null);
                XmlAttribute nameAttrib1 = doc3.CreateAttribute("Name");
                nameAttrib1.Value = _project;
                XmlAttribute nameAttrib2 = doc3.CreateAttribute("Days");
                nameAttrib2.Value = "2";
                XmlAttribute nameAttrib3 = doc3.CreateAttribute("Email");
                nameAttrib3.Value = "";
                XmlAttribute nameAttrib4 = doc3.CreateAttribute("Project");
                nameAttrib4.Value = _project;
                NewAreaNode.Attributes.Append(nameAttrib1);
                NewAreaNode.Attributes.Append(nameAttrib2);
                NewAreaNode.Attributes.Append(nameAttrib3);
                NewAreaNode.Attributes.Append(nameAttrib4);
                //append it at appropriate place
                node3.AppendChild(NewAreaNode);
                doc3.Save(HttpContext.Current.Server.MapPath(EscalationsFilePath));

                retval = true;
            }
            catch
            {
                throw;
            }
            return retval;
        }

        public ArrayList ProjectsWithTicketing()
        {
            ArrayList projects = new ArrayList();
            XmlDocument doc = new XmlDocument();
            try
            {
                //doc.Load(HttpContext.Current.Server.MapPath("/App_Data/Projects.xml"));

                doc.Load(HttpContext.Current.Server.MapPath(ProjectsPath));
                XmlNodeList projectNodes = doc.DocumentElement.SelectNodes("/projects/project");
                foreach (XmlNode projectNode in projectNodes)
                {
                    projects.Add(projectNode.Attributes["name"].Value);
                }
            }
            catch
            {

                throw;
            }
            return projects;

        }
        public void UploadReports(string teamproject)
        {
            //loop through a folder to get all rdl files
            XmlDocument doc = new XmlDocument();
            doc.Load(HttpContext.Current.Server.MapPath(ProcessConfigPath));
            XmlNode root = doc.DocumentElement;
            string reportservername = root.SelectSingleNode("/configuration/appSettings/add[@key='ReportServerName']").Attributes["value"].Value;
            string collection = root.SelectSingleNode("/configuration/appSettings/add[@key='Collection']").Attributes["value"].Value;
            string path = HttpContext.Current.Server.MapPath("/TicketM/Reports");
            //get credentials 
            string username = root.SelectSingleNode("/configuration/appSettings/add[@key='UserName']").Attributes["value"].Value;
            string password = root.SelectSingleNode("/configuration/appSettings/add[@key='Password']").Attributes["value"].Value;
            string domain = root.SelectSingleNode("/configuration/appSettings/add[@key='Domain']").Attributes["value"].Value;
            //@"C:\Users\administrator.SSGS\Documents\Reports";
            string[] files = Directory.GetFiles(path);
            foreach (string file in files)
            {
                //change the team projet name in the oroginal file
                string str = File.ReadAllText(file);
                string teamProject = "[" + teamproject + "]";
                str = str.Replace("[SSGS EMS]", teamProject);
                File.WriteAllText(file, str);
                // find only name of file 
                string[] stringSeparators = new string[] { "\\" };
                string[] result;
                result = file.Split(stringSeparators, StringSplitOptions.None);
                string reportName = result[result.Length - 1].Substring(0, result[result.Length - 1].Length - 4);
                ReportService.ReportingService2010 rs = new ReportService.ReportingService2010();

                //NetworkCredential credentials = new NetworkCredential("administrator", "P2ssw0rd", "SSGS");
                NetworkCredential credentials = new NetworkCredential(username, password, domain);
                rs.Credentials = credentials;
                rs.Url = "http://" + reportservername + "/reportserver/ReportService2010.asmx";
                //find if the folder already exists
                //this team project tp is without square brackets

                ReportService.CatalogItem[] items = rs.ListChildren("/TfsReports/" + collection + "/" + teamproject, true);
                //localhost.CatalogItem[] items = rs.ListChildren("/TfsReports/DefaultCollection/" + teamproject, true);
                ReportService.CatalogItem item = null;
                bool exists = false;
                foreach (CatalogItem folder in items)
                {
                    if (folder.Name == "TicketM")
                    {
                        // Console.WriteLine("folder exists");
                        exists = true;
                    }

                }
                //create TicketM folder if it does not exist
                if (!exists)
                {
                    item = rs.CreateFolder("TicketM", "/TfsReports/" + collection + "/" + teamproject, null);
                }
                byte[] definition = null;
                Warning[] warnings = null;
                FileStream stream = File.OpenRead(file);
                definition = new Byte[stream.Length];
                stream.Read(definition, 0, (int)stream.Length);
                stream.Close();
                rs.CreateCatalogItem("Report", reportName, "/TfsReports/" + collection + "/" + teamproject + "/TicketM", true, definition, null, out warnings);
                //rs.CreateCatalogItem("Report", reportName, "/TfsReports/DefaultCollection/" + teamproject + "/TicketM", true, definition, null, out warnings);
                //replace  file contets back to previous one
                str = File.ReadAllText(file);
                str = str.Replace(teamProject, "[SSGS EMS]");
                File.WriteAllText(file, str);


            }
        }
        #endregion
    }
}
